﻿using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LP
{
    public class Graphs : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        private PlotModel gm;
        public PlotModel GraphsModel
        {
            get { return gm; }
            set
            {
                Console.Out.WriteLine("here");
                gm = value;
                OnPropertyChanged("GraphsModel");
            }
        }

        // Construtor
        /// <summary>
        /// Constructor of Graphs class
        /// </summary>
        public Graphs ()
        {
            // Default Graph
            this.GraphsModel = new PlotModel { Title = "Gráfico" };
            this.GraphsModel.Axes.Add(new LinearAxis(AxisPosition.Bottom) { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, Title = "" });
            this.GraphsModel.Axes.Add(new LinearAxis(AxisPosition.Left) { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, Title = "" });
        }

        /// <summary>
        /// Creates a multiple line graphic.
        /// </summary>
        /// <param name="data">Array of values.</param>
        /// <param name="title">Title of the graph.</param>
        /// <param name="begin">Year of the first value.</param>
        /// <param name="end">Year of the last value.</param>
        /// <param name="xTitle">Title of the x axis.</param>
        /// <param name="yTitle">Title of the y axis.</param>
        /// <param name="infoType">Array with the designation of the different types of information the method is receiving.</param>
        public void MultipleLineChart(List<List<Double>> data, string title, int begin, int end, string xTitle, string yTitle, List<String> infoType)
        {
            this.GraphsModel = new PlotModel { Title = title };
            int i = 0;
            foreach (List<Double> section in data)
            {
                int x = begin;
                LineSeries lineSeries = new LineSeries { Title = infoType.ElementAt(i), MarkerType = MarkerType.Circle };
                
                foreach (double value in section)
                {
                    DataPoint point = new DataPoint(x, value);
                    lineSeries.Points.Add(point);
                    x += 1;
                }
                this.GraphsModel.Series.Add(lineSeries);
                i += 1;
            }
            this.GraphsModel.Axes.Add(new LinearAxis(AxisPosition.Bottom) { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, Title = xTitle });
            this.GraphsModel.Axes.Add(new LinearAxis(AxisPosition.Left) { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, Title = yTitle });

            // legenda
            this.GraphsModel.LegendTitle = "Legenda";
            this.GraphsModel.LegendOrientation = LegendOrientation.Horizontal;
            this.GraphsModel.LegendPlacement = LegendPlacement.Outside;
            this.GraphsModel.LegendBorder = OxyColors.Black;
            this.GraphsModel.LegendPosition = LegendPosition.BottomCenter;
        }

        /// <summary>
        /// Creates a multiple bar graphic.
        /// </summary>
        /// <param name="data">Array of values.</param>
        /// <param name="title">Title of the graph.</param>
        /// <param name="begin">Year of the first value.</param>
        /// <param name="end">Year of the last value.</param>
        /// <param name="xTitle">Title of the x axis.</param>
        /// <param name="yTitle">Title of the y axis.</param>
        /// <param name="infoType">Array with the designation of the different types of information the method is receiving.</param>
        public void MultipleBarChart(List<List<Double>> data, string title, int begin, int end, string xTitle, string yTitle, List<String> infoType)
        {
            this.GraphsModel = new PlotModel { Title = title };
            int x = begin;
            int i = 0;
            string[] labels = new string[end - begin + 1];

            foreach (double value in data.ElementAt(0))
            {
                labels[i] = x.ToString();
                x += 1;
                i += 1;
            }

            i = 0;
            foreach (List<Double> section in data)
            {
                ColumnSeries columnSeries = new ColumnSeries() { Title = infoType.ElementAt(i) };
                foreach (double value in section)
                {
                    ColumnItem item = new ColumnItem(value);
                    columnSeries.Items.Add(item);
                }
                this.GraphsModel.Series.Add(columnSeries);
                i += 1;
            }

            this.GraphsModel.Axes.Add(new LinearAxis(AxisPosition.Left) { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot });
            var axis = new CategoryAxis() { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot };
            axis.Labels.AddRange(labels);
            this.GraphsModel.Axes.Add(axis);


            // legenda
            this.GraphsModel.LegendTitle = "Legenda";
            this.GraphsModel.LegendOrientation = LegendOrientation.Horizontal;
            this.GraphsModel.LegendPlacement = LegendPlacement.Outside;
            this.GraphsModel.LegendBorder = OxyColors.Black;
            this.GraphsModel.LegendPosition = LegendPosition.BottomCenter;
        }

        /// <summary>
        /// Creates a multiple scatter graphic.
        /// </summary>
        /// <param name="data">Array of values.</param>
        /// <param name="title">Title of the graph.</param>
        /// <param name="begin">Year of the first value.</param>
        /// <param name="end">Year of the last value.</param>
        /// <param name="xTitle">Title of the x axis.</param>
        /// <param name="yTitle">Title of the y axis.</param>
        /// <param name="infoType">Array with the designation of the different types of information the method is receiving.</param>
        public void MultipleScatterChart(List<List<Double>> data, string title, int begin, int end, string xTitle, string yTitle, List<String> infoType)
        {
            this.GraphsModel = new PlotModel { Title = title };
            int i = 0;
            foreach (List<Double> section in data)
            {
                int x = begin;
                ScatterSeries scatterSeries = new ScatterSeries { Title = infoType.ElementAt(i), MarkerType = MarkerType.Circle };
                foreach (double value in section)
                {
                    ScatterPoint point = new ScatterPoint(x, value);
                    scatterSeries.Points.Add(point);
                    x += 1;
                }
                this.GraphsModel.Series.Add(scatterSeries);
                i += 1;
            }
            this.GraphsModel.Axes.Add(new LinearAxis(AxisPosition.Bottom) { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, Title = xTitle });
            this.GraphsModel.Axes.Add(new LinearAxis(AxisPosition.Left) { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, Title = yTitle });

            // legenda
            this.GraphsModel.LegendTitle = "Legenda";
            this.GraphsModel.LegendOrientation = LegendOrientation.Horizontal;
            this.GraphsModel.LegendPlacement = LegendPlacement.Outside;
            this.GraphsModel.LegendBorder = OxyColors.Black;
            this.GraphsModel.LegendPosition = LegendPosition.BottomCenter;
        }

        // usar com extensao ex: this.exportPDF("test.pdf");
        /// <summary>
        /// Exports graphic to PDF.
        /// </summary>
        /// <param name="filename">Name of the new file.</param>
        public void exportPDF(string fileName)
        {
            using (var stream = File.Create(fileName))
            {
                var pdfExporter = new PdfExporter() { Width = 600, Height = 400 };
                pdfExporter.Export(this.GraphsModel, stream);
            }
        }

        // usar com extensao ex: this.exportSVG("test.svg");
        /// <summary>
        /// Exports graphic to SVG.
        /// </summary>
        /// <param name="filename">Name of the new file.</param>
        public void exportSVG(string fileName)
        {
            using (var stream = File.Create(fileName))
            {
                var exporter = new SvgExporter() { Width = 600, Height = 400 };
                exporter.Export(this.GraphsModel, stream);
            }
        }

    }
}
